/*
Problem Description
上次Gardon的迷宫城堡小希玩了很久（见Problem B），现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样，首先她认为所有的通道都应该是双向连通的，
就是说如果有一个通道连通了房间A和B，那么既可以通过它从房间A走到房间B，也可以通过它从房间B走到房间A，为了提高难度，小希希望任意两个房间有且仅有一条路径可以相通（除非走了回头路）。
小希现在把她的设计图给你，让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子，前两个是符合条件的，但是最后一个却有两种方法从5到达8。 

Input
输入包含多组数据，每组数据是一个以0 0结尾的整数对列表，表示了一条通道连接的两个房间的编号。房间的编号至少为1，且不超过100000。每两组数据之间有一个空行。 
整个文件以两个-1结尾。
Output
对于输入的每一组数据，输出仅包括一行。如果该迷宫符合小希的思路，那么输出"Yes"，否则输出"No"。
Sample Input
6 8  5 3  5 2  6 4
5 6  0 0

8 1  7 3  6 2  8 9  7 5
7 4  7 8  7 6  0 0

3 8  6 8  6 4
5 3  5 6  5 2  0 0

-1 -1
Sample Output
Yes
Yes
No
 */
package com.yuan.algorithms.training20150807;

import java.io.BufferedInputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;

/**
 * @author YouYuan
 * @eMail E-mail:1265161633@qq.com
 * @Time 创建时间：2015年8月23日 上午10:55:20
 * @Explain 说明:
 */
public class 小希的迷宫 {

	static int[] A = new int[100005];//并查集数组
	static Scanner in = new Scanner(new BufferedInputStream(System.in));
	static HashSet<Integer> vertex = new HashSet<Integer>();//用于存储顶点
	static int m;//记录边的数量
	
	public static void main(String[] args) {
		for (int i = 0, len = A.length; i < len; i++) {
			A[i] = i;
		}
		while (in.hasNext()) {
			initialise();//初始化数据
			int a = in.nextInt();
			int b = in.nextInt();
			if (a == 0 && b == 0) {//0 0情况是一个点也没有，也属于满足条件
				System.out.println("Yes");
				continue;
			}
			if (a == -1 && b == -1) {
				break;
			}
			while (a != 0 && b != 0) {
				vertex.add(a);
				vertex.add(b);
				m++;//累加边的数量
				merge(a, b);//并查集，合并区间
				a = in.nextInt();
				b = in.nextInt();
			}
			int sum = 0;//记录根节点的数量
			Iterator<Integer> it = vertex.iterator();//获取vertex的迭代器
			while(it.hasNext()) {
				int k = it.next();
				if (A[k] == k) {//相等说明是根节点
					sum++;//根节点总数+1
				}
			}
			if (sum==1 && m - vertex.size() == -1) {//仅有一个根节点且边数比顶点数少一个（每个顶点间只有一条边），则符合题目要求
				System.out.println("Yes");
			} else {
				System.out.println("No");
			}
		}
	}

	private static void merge(int a, int b) {
		int tempA = find(a);
		int tempB = find(b);
		if (tempA != tempB) {
			A[tempA] = A[tempB];
		}
	}

	private static int find(int a) {
		while(A[a] != a) {
			a = A[a];
		}
		return a;
	}

	private static void initialise() {
		m = 0;
		Iterator<Integer> it = vertex.iterator();
		while(it.hasNext()) {
			int k = it.next();
			A[k] = k;//恢复数据到初始状态
		}
		vertex.clear();
	}

}
